//确保浏览器支持WebSocket ie10及以上
//参考http://www.ruanyifeng.com/blog/2017/05/websocket.html
/**
* shieldChat
* @fileOverview 基于websocket协议的聊天，依赖moment.js（日期处理,参考http://momentjs.cn/）和ShieldJS.main.js（debug调试）和jquery.cookie.js(保存聊天记录)
* @author kevin Lv
* @email donggongai@126.com
* @version 1.0.0
* @date 2019-03-01
*/
;(function($){
	/**
	* @author kevin Lv
	* @constructor shieldChat
	* @description 基于websocket协议的聊天，依赖moment.js（日期处理,参考http://momentjs.cn/）和ShieldJS.main.js（debug调试）
	* @see The <a href="#">kevin</a>
	* @example
	*	$("#chat").shieldChat({serviceURL:"url地址"});
	*   带其他参数
	*	$("#chat").shieldChat({
			serviceURL:"服务器端地址",
			nickNameInputE : "昵称输入框",
			realNameInputE : "姓名输入框",
	    	chatSendAllE : "群发", 
	    	msgInputE : "消息输入框", 
	    	chatUsersInputE : "用户列表下拉框", 
	    	chatMessagesE : "聊天信息内容", 
	    	chatMessageDivE : "聊天信息div（容器，包裹$chatMessagesE）"
		});
	* @since version 1.0.0
	*/
	$.fn.shieldChat = function(options){
		if (!window.WebSocket) {
			ShieldJS.debug("选择器["+this.selector+"]调用自定义插件 shieldChat，不支持WebSocket协议");
			return false;
		} 
		ShieldJS.debug("选择器["+this.selector+"]调用自定义插件 shieldChat，调用元素数 "+this.size()+" 个[jQuery "+this.jquery+"]");
		/**
		* @description {Json} 设置参数选项
		* @field
		*/
		var options = $.extend({}, $.fn.shieldChat.defaults, options);
		/**
		* @description 处理函数
		*/
		return this.each(function() {
			var chatWSocket;
			var serviceLocation = options.serviceURL;
			if (!serviceLocation) {
				ShieldJS.error("shieldChat未设置serviceURL");
				return;
			}
			var $chatContainerE = $(this); //完整的容器
			var $realNameInputE;
		    var $chatSendAllE; //群发(废弃)
		    var $msgInputE; // 消息输入框
		    var $chatUsersInputE; //用户列表下拉框
		    var $chatMessagesE; //聊天信息内容
		    var $chatMessageDivE; //聊天信息div（容器，包裹$chatMessagesE）
		    
		    var chatRoomName = '';
		    var chatToolbarE; //toolbar
		    var chatIsMin = false;
		    var noreadNo = 0;
		    var chatUserId; //当前用户id(可从session中获取)
		    var chatMouseWitch = 0; //鼠标点击值
		    var chatIntervalMethod; //定时获取
		    var localChatMsgKey = options.localChatMsgKey;
			
			$nickNameInputE = $chatContainerE.find(options.nickNameInputE);
	        $msgInputE = $chatContainerE.find(options.msgInputE);
	        $chatMessagesE = $chatContainerE.find(options.chatMessagesE);
	        $chatUsersInputE = $chatContainerE.find(options.chatUsersInputE);
	        $chatMessageDivE = $chatContainerE.find(options.chatMessageDivE);
	        $realNameInputE = $chatContainerE.find(options.realNameInputE);
	        $chatSendAllE = $chatContainerE.find(options.chatSendAllE);
	        chatToolbarE = $chatContainerE.find(".toolbar");
	        $('.chat-wrapper').hide();
	        $chatContainerE.show(); //显示
	        $nickNameInputE.focus();
	        chatUserId = $("#chatuserId").val();
	  
	        $chatContainerE.find('#enterRoom').click(function(evt) { //登录房间
	            evt.preventDefault();
	            connect2Chatserver(); //连接到服务器
	            $('.chat-wrapper .chatTitle').text('会话 # '+$nickNameInputE.val() + "("+$realNameInputE.val()+")@" + chatRoomName);
	            $('.chat-signin').hide();
	            $('.chat-wrapper').show();
	            $msgInputE.focus();
	            
	            chatIntervalMethod = setInterval(function(){
	            	ShieldJS.debug("websocket chat获取用户列表")
	            	if (chatWSocket) {
	            		sendMessage("userList");
	                }
	    		}, 1000*60*10); //10分钟定时获取用户列表，防止用户列表不刷新 1000*60*10
	        });
	        
	        // 发送消息
	        $chatContainerE.find('#sendbtn').click(function(evt) {
	            evt.preventDefault();
	            sendMessage();
	        });
	        // 退出房间
	        $chatContainerE.find('#leave-room').click(function(){
	            leaveRoom();
	        });
	        // 关闭会话
	        $chatContainerE.find('#closechat').click(function(){
	            closeChat();
	        });
	        // 最小化
	        $chatContainerE.find('#minchat').click(function(){
	            minChat();
	        });
	        // 还原窗口
	        $chatContainerE.find('#returnchat,.newtips,.noread').click(function(){
	            returnChat();
	        });
	        // 回车发送
	        $chatContainerE.find("#message").bind('keypress', function (e) {
	    	    var key = e.which;
	    	    if ( key == 13 || (e.ctrlKey && key == 13 ) ) {
	    	        e.preventDefault();
	    	        sendMessage();
	    	    }
	    	});
	        // 获取鼠标点击
	        $chatMessageDivE.mousedown(function(e){
	        	chatMouseWitch = e.which; //有三个值 1 左击 2 中间按钮 3 右击
	        	ShieldJS.debug("mouseWitch mousedown"+chatMouseWitch);
	        });
	        $chatMessageDivE.mouseup(function(){
	        	chatMouseWitch = 0;
	        	ShieldJS.debug("mouseWitch mouseup"+chatMouseWitch);
	        });
	        // 监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
	        // 火狐谷歌刷新或者关闭窗口时会自动断开连接，ie不行，所以增加此方法
	        window.onbeforeunload = function() {
	        	if (chatWSocket) {
	        		chatWSocket.close();
	            }
	        }
	        //自动登录并最小化
	        //$chatContainerE.find('#enterchatIsMin').click();
	        //$chatContainerE.find('#minchat').click();
	        // ====================处理方法===================
	        // 接收消息
	        function onMessageReceived(evt) {
	        	var msg = JSON.parse(evt.data); // native API 
	        	if (msg.msgType == "userList") { //在线人员
	        		var optionHtml = '<option value="">在线人员</option>';
	        		var otherDevices = new Array();
	        		var users = new Array();
	        		$.each(msg.users, function(i, user) {
	        			if (chatUserId == user.id) {
	        				otherDevices.push(user);
	        				//optionHtml += '<option title="'+user.realName+'['+user.ip+","+user.client+']" value="'+user.id+'" disabled="disabled" >' + user.realName + '[我]</option>';
	        			}else{
	        				users.push(user);
	        				//optionHtml += '<option title="'+user.realName+'['+user.ip+","+user.client+']" value="'+user.id+'">' + user.realName + '</option>';
	        			}
	        		});
	        		if (otherDevices.length>0) {
	        			optionHtml += '<optgroup id="otherDevices" label="其他设备">';
	        			$.each(otherDevices, function(i, user) {
	        				optionHtml += '<option title="'+user.realName+'['+user.ip+","+user.client+']" value="'+user.id+'" disabled="disabled" >' + user.realName + '[我]</option>';
	        			});
	        			optionHtml += '</optgroup>';
	        		}
	        		if (users.length>0) {
	        			optionHtml += '<optgroup id="otherDevices" label="在线用户">';
	        			$.each(users, function(i, user) {
	        				optionHtml += '<option title="'+user.realName+'['+user.ip+","+user.client+']" value="'+user.id+'">' + user.realName + '</option>';
	        			});
	        			optionHtml += '</optgroup>';
	        		}
//	        		alert("outer:::"+$chatUsersInputE.prop("outerHTML"))
	        		$chatUsersInputE.html(optionHtml);
	        		$("#chatusersonlinenum").text(msg.users.length);
	        	} else if (msg.msgType == "chat") { //会话消息
	        		var $messageLine = showMessage2Tr(msg.received, msg.receivedTime, msg.senderName, msg.message);
	        		
	        		if ($chatMessagesE.height()>200 && chatMouseWitch != 1) { //超过高度,且鼠标左键未按下（）则自动滚动显示最新的信息
	        			$chatMessageDivE.animate({
	        				scrollTop: $chatMessagesE.height() - 200 + 2
	        			},100);
	        		}
	        		if (msg.sender !='系统消息' && chatIsMin) { //非系统消息并且未最小化状态，设为未读
	        			noreadNo++;
	        			if(chatToolbarE){
	        				chatToolbarE.find(".newtips").show();
	        				chatToolbarE.find(".noread").text("("+noreadNo+")").show();
	        				winNotification("有来自“绿盾软件管理中心”的未读消息"+ noreadNo+ "条！");
	        			}
	        		}
	        		// 保存历史记录
	        		saveLocalStorageMsg();
	        	}
	        }
	        
	       
	        // 获取展示信息的tr
	        function showMessage2Tr(receivedDateTime, receivedTime, senderName, message ) {
	        	var receivedDate = receivedDateTime.substr(0, 10); //日期
	        	var diffDays = moment(receivedDate, 'YYYY-MM-DD').diff(moment(), 'days');
	        	var messageHtml = "";
        		if ($chatMessagesE.find(".historyDate:contains('"+receivedDate+"')").length == 0) {
        			messageHtml += '<tr class="dateTr noStorage"><td colspan="3" class="historyDate" title="' + receivedDate + '">' + receivedDate ;
        			if (diffDays == 0) {
        				messageHtml += ' (今天)';
                    } else {
                    	messageHtml += ' (' + moment(receivedDate, "YYYY-MM-DD").fromNow() + ')';
                    }
        			messageHtml += '</td></tr>';
                }
	        	messageHtml += '<tr><td class="received" title="' + receivedDateTime + '">' + receivedTime
    			+ '</td><td class="user label label-info">' + senderName
    			+ '</td><td class="message badge"><span class="messageCont">' + message
    			+ '</span></td></tr>';
	        	var $messageLine = $(messageHtml);
	        	if (senderName == '系统消息') {
	        		$messageLine.addClass("systemMsg noStorage");
	        	}
	        	$chatMessagesE.append($messageLine);
	        	return $messageLine;
	        }
	        // 桌面提醒
	        function winNotification(message) {
	        	if ('Notification' in window) { //需要浏览器支持
	        		Notification.requestPermission().then(function(result){
	        			if(result=='granted'){
	        				var notification = new Notification('消息提醒', {
	        					dir: "auto",
	        					lang: "hi",
	        					body: message
	        				});
	        				setTimeout(function(){
	        					notification.close();
	        				}, 4000);
	        			}
	        		})
	        	}
	        }	
	        
	        // 发送消息
	        function sendMessage(msgType) {
	        	if (chatWSocket && chatWSocket.readyState == WebSocket.OPEN ) { //CONNECTING：值为0，正在连接。OPEN：值为1，连接成功。	CLOSING：值为2，连接正在关闭。CLOSED：值为3，连接已经关闭或打开连接失败。
	        		if (!msgType || msgType == "chat") { //聊天
	        			var msg = '{"message":"' + $msgInputE.val() + '", "sender":"' 
	        			+ $nickNameInputE.val() + '", "senderName":"' + $realNameInputE.val() +'","received":"","sendAll":"'
	        			+ ($chatSendAllE.prop("checked")?1:0) + '","receiver":"' + $chatUsersInputE.val() + '"';
	        			if (msgType) {
	        				msg += ',"msgType":"' + msgType + '"';
	        			}
	        			msg += '}';
	        			$msgInputE.val('').focus();
	        		} else { //userList,ping
	        			var msg = '{"msgType":"' + msgType + '","sender":"'	+ $nickNameInputE.val() + '", "senderName":"' + $realNameInputE.val() +'"}';
	        		}
	        		chatWSocket.send(msg);
	        	}
	        }
	        //连接到服务器
	        function connect2Chatserver() {
	        	// 获取历史记录
	        	loadLocalStorageMsg();
	        	
	        	chatRoomName = $('#chatroom option:selected').val();
	        	chatUserId = $("#chatuserId").val();
	        	chatWSocket = new WebSocket(serviceLocation + chatRoomName+"/"+chatUserId);
	        	chatWSocket.onmessage = onMessageReceived;
	        }
	        // 获取浏览器支持情况 参考:http://www.cnblogs.com/st-leslie/p/5617130.html
	        function isSupportLocalStorage(){
	        	if (!window.localStorage) {
	        		ShieldJS.debug("浏览器不支持localStorage，将使用cookie对本地信息进行存储！");
	        		return false;
	        	}
	        	return true;
	        }
	        // 保存历史聊天记录
	        function saveLocalStorageMsg(){
        		var msgTrEles = $chatMessagesE.find("tr:not(.noStorage)");
        		if (msgTrEles.length > 0) {
        			var storageMsg = '{"messages":[';
        			$.each(msgTrEles, function(i, trObj) {
        				var trObj = $(trObj);
        				if (i>0) {
        					storageMsg += ",";
        				}
        				storageMsg += '{"receivedTime":"' + trObj.find("td:eq(0)").attr("title") + '","senderName":"' + trObj.find("td:eq(1)").html() + '","message":"' + trObj.find(".messageCont").html() + '"}';
        			});
        			storageMsg += ']}';
        			saveMsg2Local(localChatMsgKey, storageMsg); //保存
        		}
	        }
	        // 保存信息到本地
	        function saveMsg2Local(key, value){
    			if(isSupportLocalStorage()){ //支持localStorage
    				localStorage.setItem(key, value);
    			} else { //不支持localStorage，放到cookie中
    				$.cookie(key, value, {path:'/', expires:3650});
				}
	        }
	        // 从本地保存的信息中获取
	        function getMsgFromLocal(key) {
	        	var value;
	        	if(isSupportLocalStorage()){
	        		value = localStorage.getItem(key);
                } else {
                	value = $.cookie(key);
                }
	        	return value;
	        }
	        // 加载历史记录
	        function loadLocalStorageMsg() {
	        	var chatmsg = getMsgFromLocal(localChatMsgKey);
	        	if (chatmsg) {
	        		var msg = JSON.parse(chatmsg); // native API
	        		$.each(msg.messages, function(i, message) {
	        			var $messageLine = showMessage2Tr(message.receivedTime, message.receivedTime ? message.receivedTime.substr(10) : "", 
	        					message.senderName, message.message);
	        		});
	        	}
	        }
	        //离开房间
	        function leaveRoom() {
	        	chatWSocket.close();
	        	if (chatIntervalMethod) {
	        		clearInterval(chatIntervalMethod);
	        	}
	        	$chatMessagesE.empty();
	        	$('.chat-wrapper').hide();
	        	$('.chat-signin').show();
	        	$nickNameInputE.focus();
	        }
	        // 最小化
	        function minChat() {
	        	chatIsMin = true;
	        	$chatContainerE.find(".content").hide();
	        	$chatContainerE.find("#returnchat").show();
	        	$chatContainerE.find("#minchat").hide();
	        }
	        //  还原
	        function returnChat() {
	        	chatIsMin = false;
	        	noreadNo = 0;
	        	chatToolbarE.find(".newtips").hide();
	        	chatToolbarE.find(".noread").text("").hide();
	        	$chatContainerE.find(".content").show();
	        	$chatContainerE.find("#minchat").show();
	        	$chatContainerE.find("#returnchat").hide();
	        }
	        // 关闭会话界面
	        function closeChat() {
	        	chatToolbarE.find(".newtips").hide();
	        	chatToolbarE.find(".noread").text("").hide();
	        	$chatContainerE.hide();
	        	chatIsMin = false;
	        }
	        
	        //心跳检测
	        var heartCheck = {
	        		timeout: 540000,        //9分钟发一次心跳
	        		timeoutObj: null,
	        		serverTimeoutObj: null,
	        		reset: function(){
	        			clearTimeout(this.timeoutObj);
	        			clearTimeout(this.serverTimeoutObj);
	        			return this;
	        		},
	        		start: function(){
	        			var self = this;
	        			this.timeoutObj = setTimeout(function(){
	        				//这里发送一个心跳，后端收到后，返回一个心跳消息，
	        				//onmessage拿到返回的心跳就说明连接正常
	        				chatWSocket.send("ping");
	        				console.log("ping!")
	        				self.serverTimeoutObj = setTimeout(function(){ //如果超过一定时间还没重置，说明后端主动断开了
	        					chatWSocket.close();     //如果onclose会执行reconnect，我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
	        				}, self.timeout);
	        			}, this.timeout)
	        		}
	        }
		});

	};
	$.fn.shieldChat.defaults = {
		/** 服务器端地址 */
		serviceURL:"",
		/** 昵称输入框 */
		nickNameInputE : "#nickname",
		/** 姓名输入框 */
		realNameInputE : "#chatRealName",
		/** 群发(废弃) */
	    chatSendAllE : "#sendall", 
	    /** 消息输入框 */
	    msgInputE : "#message", 
	    /** 用户列表下拉框 */
	    chatUsersInputE : "#usersonline", 
	    /** 聊天信息内容 */
	    chatMessagesE : "#response", 
	    /** 聊天信息div（容器，包裹$chatMessagesE） */
	    chatMessageDivE : "#responseDiv",
	    /** 本地保存聊天记录的可以 */
	    localChatMsgKey : "chatmsg"
	}
})(jQuery);